#requires -version 2.0 
function Get-NaSnapshot {
	<#
	.Synopsis
   		Return snapshot information for a specified volume.
	.Description
	 	Return snapshot information for a specified volume. A list of snapshots and information about 
 		each snapshot is returned.
	.Parameter Name
   		Name of the object on which to list the snaplist information. 
	.Parameter Type
   		Type of the object on which to list the snaplist information. Possible values: volume, aggregate. 
	.Parameter LunClone
  		Check if snapshot contains any lun clones.
	.Parameter Quick
   		the snapshot block ownership values, namely the total and cumulativeTotal outputs, will be omitted.
 		Use of this option can be helpful if there is an ongoing single file snap restore, as the block 
 		ownership calculation may take a substantial amount of time during the restore.
	.Parameter Server
   		NaServer to query
	.Example
		# Get all snapshot's on vol1
 		Get-NaVol vol1 | Get-NaSnapshot 
	.Example
		# Get all snapshot's on vol1 that are older then 30 days
	 	Get-NaVol vol1 | Get-NaSnapshot | ? {$_.Created -gt (get-date).adddays(-30)}
	.Outputs
    	NetApp.SDK.NaSnapshot[]
    .Link
    	New-NaSnapshot
		Remove-NaSnapshot
		Rename-NaSnapshot
		Restore-NaSnapshot
		Measure-NaSnapshot
	#>
	[CmdletBinding(SupportsShouldProcess=$FALSE,SupportsTransactions=$False,ConfirmImpact="None",DefaultParameterSetName="")]
	param ( 
	[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume/aggregate for which we want status information.")]
	[Alias("Aggregate")] 
	[STRING]
	$Volume,

	[Parameter(Mandatory=$false,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Type of the object on which to list the snaplist information. Possible values: volume, aggregate.")]
	[STRING]
	$Type = 'volume',

	[Parameter(Mandatory=$False,ValueFromPipelineByPropertyName=$False,HelpMessage="Name of the object on which to list the snaplist information.")]
	[STRING]
	$Name,

	[switch]
	$LunClone,

	[switch]
	$Quick,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-list-info")
		switch ($type){
			"flex" {$request.AddNewChild("target-type","volume")}
			"vol" {$request.AddNewChild("target-type","volume")}
			"volume" {$request.AddNewChild("target-type","volume")}
			"trad" {$request.AddNewChild("target-type","volume")}
			"aggregate" {$request.AddNewChild("target-type","aggregate")}
			"aggr" {$request.AddNewChild("target-type","aggregate")}
			default {$request.AddNewChild("target-type","volume")}
		}
		$request.AddNewChild("target-name",$Volume)
		$request.AddNewChild("snapowners",$TRUE)
		if ($LunClone) {
			$request.AddNewChild("lun-clone-snapshot",$TRUE)
		}
		if ($Quick) {
			$request.AddNewChild("terse",$TRUE)
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result.snapshots."snapshot-info" |
			Where-Object {$_.name}|% {
				New-Object NetApp.SDK.NaSnapshot -ArgumentList @(
				$_."name",
				(ConvertFrom-NaTime $_."access-time"),
				(ConvertFrom-NaBool $_."busy"),
				(ConvertFrom-NaBool $_."contains-lun-clones"),
				$_."cumulative-percentage-of-total-blocks",
				$_."cumulative-percentage-of-used-blocks",
				$_."cumulative-total",
				$_."dependency",
				$_."percentage-of-total-blocks",
				$_."percentage-of-used-blocks",
				[array]$_."snapshot-owners-list"."snapshot-owner",
				$_."total",
				$Volume
				)
			} | Where-Object {$_.Snapshot -match $name}
		}
	}
}
function New-NaSnapshot {
	<#
	.Synopsis
   		Create a new snapshot on a specified volume.
	.Description
	 	Create a new snapshot on a specified volume.
	.Parameter Name
   		Name of the snapshot to be created. The maximum string length is 256 characters. 
	.Parameter Volume
   		Name of the volume on which the snapshot is to be created. The volume name
   		can contain letters, numbers, and the underscore character (_), but the first
   		character must be a letter or an underscore
	.Parameter LunClone
   		Check if snapshot contains any lun clones.
	.Parameter ASync
   		The snapshot is to be created asynchronously.
	.Parameter Server
   		NaServer to query
	.Example
		# Create a new snapshot named snap1 on vol1
	 	PS > New-NaSnapshot -name snap1 -volume vol1
	.Outputs
    	NetApp.SDK.NaSnapshot[]
    .Link
		Get-NaSnapshot
		Remove-NaSnapshot
		Rename-NaSnapshot
		Restore-NaSnapshot
		Measure-NaSnapshot
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param(
	[Parameter(Position=0,Mandatory=$TRUE,HelpMessage="Name of the snapshot to be created. The maximum string length is 256 characters.")]
	[STRING]
	$Name,

	[Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume on which the snapshot is to be created.")]
	[Alias("Aggregate")] 
	[STRING]
	$Volume,

	[switch]
	$LunClone,

	[switch]
	$ASync,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-create")
		$request.AddNewChild("snapshot",$name)
		$request.AddNewChild("volume",$volume)
		if ($LunClone) {
			$request.AddNewChild("is-valid-lun-clone-snapshot",$TRUE)
		}
		if ($async) {
			$request.AddNewChild("async",$TRUE)
		}
		if ($pscmdlet.ShouldProcess($volume, "Creating New Snapshot $name ")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($? -and -not $async){
				return Get-NaSnapshot -Name $Name -Volume $volume -type "volume" -server $server
			}
		} 
	}
}
function Remove-NaSnapshot {
	<#
	.Synopsis
   		Delete a snapshot on a specified volume. 
	.Description
	 	Delete a snapshot on a specified volume. 

	 	Note:  	EONTAPI_EBUSY is returned when the snapshot is in use. 
 				EONTAPI_EROFS is returned when the volume is read-only. 
 				EONTAPI_EAGAIN is returned when splitting a blockmap or reverting.
	.Parameter Name
   		Name of snapshot to be deleted on the specified volume. 
	.Parameter Volume
   		Name of the volume on which the snapshot is to be deleted. 
	.Parameter Server
   		NaServer to query
	.Example
		# Delete snap1 from vol1
	 	PS > Remove-NaSnapshot -Name snap1 -volume vol1
    .Link
		Get-NaSnapshot
		New-NaSnapshot
		Rename-NaSnapshot
		Restore-NaSnapshot
		Measure-NaSnapshot
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param(
	[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of snapshot to be deleted on the specified volume.")]
	[Alias("snapshot")]
	[STRING]
	$Name,

	[Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume on which the snapshot is to be deleted.")]
	[Alias("Aggregate")] 
	[STRING]
	$volume,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-delete")
		$request.AddNewChild("snapshot",$name)
		$request.AddNewChild("volume",$volume)
		if ($pscmdlet.ShouldProcess($server.server, "Deleting snapshot $($name) from $($volume)")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}
function Rename-NaSnapshot {
	<#
	.Synopsis
  		Rename a specified snapshot to a new name on a specified volume.
	.Description
	 	Rename a specified snapshot to a new name on a specified volume.
	.Parameter NewName
   		New name of snapshot as a result of the rename. 
	.Parameter Name
   		Name of snapshot to be renamed. 
	.Parameter Volume
   		Name of the volume where the current snapshot and the new snapshot are located. 
	.Parameter Server
   		NaServer to query
	.Example
		# Delete snap1 from vol1
 		Rename-NaSnapshot -Name snap1 -newname snap2 -volume vol1
	.Outputs
    	NetApp.SDK.NaSnapshot[]
    .Link
		Get-NaSnapshot
		New-NaSnapshot
		Remove-NaSnapshot
		Restore-NaSnapshot
		Measure-NaSnapshot
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param(
	[Parameter(Position=0,Mandatory=$TRUE,HelpMessage="New name of snapshot as a result of the rename.")]
	[STRING]
	$NewName,

	[Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of snapshot to be renamed.")]
	[Alias("Snapshot")]
	[STRING]
	$Name,

	[Parameter(Position=2,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume where the current snapshot and the new snapshot are located.")]
	[Alias("Aggregate")] 
	[STRING]
	$volume,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-rename")
		$request.AddNewChild("current-name",$name)
		$request.AddNewChild("new-name",$NewName)
		$request.AddNewChild("volume",$volume)
		if ($pscmdlet.ShouldProcess($server.server, "Renaming snapshot $Name to $NewName ")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($? -and -not $async){
				return Get-NaSnapshot -Name $NewName -Volume $volume -type "volume" -server $server
			}
		} 
	}
}
function Restore-NaSnapshot {
	<#
	.Synopsis
   		Reverts a volume to a specified snapshot.
	.Description
	 	Reverts a volume to a specified snapshot. The volume must be online and must not be a mirror. If reverting the
	 	root volume, the filer will be rebooted. Non-root volumes do not require a reboot. A volume cannot have both a
	 	volume snaprestore and a single-file snaprestore executing simultaneously. Multiple single-file snaprestores 
	 	can be in progress simultaneously. After the reversion, the volume is in the same state as it was when the 
	 	snapshot was taken.
	.Parameter Snapshot
		The snapshot to restore to, retrieve with Get-NaSnapshot.
	.Parameter Name
   		Name of snapshot to restore from.
	.Parameter Volume
	  	Name of volume to restore. 
	.Parameter Server
   		NaServer to query
	.Example
		# revert vol1 back to snap2
	 	PS > Restore-NaSnapshot -Name snap1 -volume vol1
	.Example
		# revert vol1 back to snap2
		Get-NaSnapshot -
	 	PS > Restore-NaSnapshot -Name snap1 -volume vol1
	.Outputs
    	NetApp.SDK.NaSnapshot[]
    .Link
		Get-NaSnapshot
		New-NaSnapshot
		Remove-NaSnapshot
		Rename-NaSnapshot
		Measure-NaSnapshot
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="high",DefaultParameterSetName="byObject")]
	param(
	[Parameter(ParameterSetName="byObject",Mandatory=$TRUE,ValueFromPipeline=$TRUE,HelpMessage="Snapshot to restore to.")]
	[NetApp.SDK.NaSnapshot[]]
	$Snapshot,

	[Parameter(ParameterSetName="byString",Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of snapshot to restore from.")]
	[string]
	$Name,

	[Parameter(ParameterSetName="byString",Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of volume to restore.")]
	[Alias("Aggregate")] 
	[STRING]
	$volume,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		switch ($PSCmdlet.ParametersetName)
		{
			"byObject" 
			{
				foreach ($S in $Snapshot) {
					$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-restore-volume")
					$request.AddNewChild("snapshot",$S.Name)
					$request.AddNewChild("volume",$S.Volume)
					if ($pscmdlet.ShouldProcess($server.server, "Restoring $($S.Volume) from snapshot $($S.Name)")) {
						try {
							$server.InvokeElem($request)|out-null
						}
						catch [NetApp.Manage.NaApiFailedException]{
							Write-Warning $_.Exception.GetBaseException().message
							continue;
						}
					}
				}
			}
			"byString"
			{
				$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-restore-volume")
				$request.AddNewChild("snapshot",$Name)
				$request.AddNewChild("volume",$volume)
				if ($pscmdlet.ShouldProcess($server.server, "Restoring $($Volume) from snapshot $($Name)")) {
					try {
						$server.InvokeElem($request)|out-null
					}
					catch [NetApp.Manage.NaApiFailedException]{
						Write-Warning $_.Exception.GetBaseException().message
						continue;
					}
				}
			}
		}
	}
}
function Measure-NaSnapshot {
	<#
	.Synopsis
   		Returns the amount of space consumed between two snapshots or a snapshot and active filesystem. 
	.Description
	 	Returns the amount of space consumed between two snapshots or a snapshot and active filesystem. 
	.Parameter Snapshot1
   		Name of snapshot to be compared with snapshot2 for space consumption calculations.
   		If Snapshot2 is omited then the snapshot is compared with the active file system.
	.Parameter Volume
  		Name of the volume on which the snapshot delta is to calculated
  	.Parameter Snapshot2
  		Name of snapshot to be compared with snapshot1 for space consumption calculations.
	.Parameter Server
   		NaServer to query
	.Example
		# Get the size of snap1 on vol1
 		PS > Measure-NaSnapshot -Snapshot1 snap1 -volume vol1
 	.Example
		# Get the delta size of snap2 vs snap1 on vol1
 		PS > Measure-NaSnapshot -Snapshot1 snap1 -snapshot2 snap2 -volume vol1
	.Outputs
    	PSObject[]
    .Link
    	Get-NaSnapshot
	#>
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="none",DefaultParameterSetName="")]
	param (
	[Parameter(position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of snapshot to be compared with snapshot2 for space consumption calculations.")]
	[alias("Snapshot")]
	[STRING]
	$Snapshot1,

	[Parameter(position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of the volume on which the snapshot delta is to calculated.")]
	[Alias("Aggregate")]
	[STRING]
	$Volume,

	[Parameter(position=2,HelpMessage="Name of snapshot to be compared with snapshot1 for space consumption calculations.")]
	[STRING]
	$Snapshot2,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-delta-info")
		$request.AddNewChild("volume",$Volume)
		$request.AddNewChild("snapshot1",$snapshot1)
		if ($snapshot2) {
			$request.AddNewChild("snapshot2",$snapshot2)
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			return $result | select-object @{
				Expression={$Snapshot1}
				Name='Name'
			},@{
				Expression={[math]::Round($_."consumed-size"/1mb,2)}
				Name='ConsumnedSizeMB'
			},@{
				Expression={[timespan]::FromSeconds($_."elapsed-time")}
				Name='ElapsedTime'
			} 
		}
	}
}

function Get-NaSnapshotReserve {
	<#
	.Synopsis
   		Gets the percentage of disk space that is reserved for snapshots in the
		indicated volume.
	.Description
	 	Gets the percentage of disk space that is reserved for snapshots in the
		indicated volume. If no volume is specified, this will return the percentage of
		disk space reserved for snapshots for each of the volumes in the system. Reserve
		space can be used only by snapshots and not by the active file system.
	.Parameter Name
		Volume to get percentage of space reserved for snapshots. 
	.Parameter Server
   		NaServer to query
	.Outputs
    	NetApp.SDK.NaSnapshotReserve[]
    .Link
    	Set-NaSnapshotReserve
    .Example
    	# Get the current snapshot reserve settings for vol0
    	PS > Get-NaSnapshotReserve -Name vol0
	#>
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
	[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Volume to get percentage of space reserved for snapshots.")]
	[alias("volume")]
	[STRING]
	$Name,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-reserve-list-info")
		if ($name) {
			$request.AddNewChild("volume",$name)
		}
		try {
			$result = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			$result."snapshot-reserve-details"."snapshot-reserve-detail-info" | % {
				return New-Object NetApp.SDK.NaSnapshotReserve -ArgumentList @(
				$_.volume,
				$_.percentage,
				$_.size
				)
			}
		}
	}
}
function Set-NaSnapshotReserve {
	<#
	.Synopsis
   		Sets the size of the indicated volume's snapshot reserve to the specified
		percentage.
	.Description
	 	Sets the size of the indicated volume's snapshot reserve to the specified
		percentage. Reserve space can be used only by snapshots and not by the active
		file system.
	.Parameter Percentage	
		Percentage to set. Range [0-100].
	.Parameter Name
		Name of volume on which to set the snapshot space reserve. 
	.Parameter Server
   		NaServer to query
	.Outputs
    	NetApp.SDK.NaSnapshotReserve[]
    .Link
    	Get-NaSnapshotReserve
    .Example
    	# Set the snapshot reserve for vol0 to 20%
    	PS > Set-NaSnapshotReserve -Percentage 20 -Name vol0
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param (
	[Parameter(Position=0,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Percentage to set. Range [0-100].")]
	[ValidateRange(0,100)]
	[int]
	$Percentage,

	[Parameter(Position=1,Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Name of volume on which to set the snapshot space reserve.")]
	[Alias("Volume")]
	[STRING]
	$Name,

	[Parameter(
	HelpMessage="NaServer to query"
	)]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-set-reserve")
		$request.AddNewChild("volume",$name)
		$request.AddNewChild("percentage",$Percentage)
		if ($pscmdlet.ShouldProcess($Server.server, "Setting $($Name) snapshot reserve to $($Percentage)%")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaSnapshotReserve -name $Name -Server $server
			}
		} 
	}
}

function Get-NaSnapshotAutoDelete {
	<#
	.Synopsis
   		Returns the current snapshot autodelete settings.
	.Description
	 	Returns the current snapshot autodelete settings.
	.Parameter Name
		Name of the existing volume for which we want snapshot autodelete settings 
	.Parameter Server
   		NaServer to query
	.Outputs
    	NetApp.SDK.NaSnapshotAutoDelete[]
    .Link
    	Set-NaSnapshotAutoDelete
    .Example
    	# Get the autodelet policy for vol0
    	PS > Get-NaSnapshotAutoDelete -Name vol0
	#>
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
	[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Alias("Volume")]
	[STRING]
	$Name,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$result = @{}
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-autodelete-list-info")
		$request.AddNewChild("volume",$Name)
		try {
			([xml]$server.InvokeElem($request)).results.options."snapshot-autodelete-info"|%{$result += @{$_."option-name"=$_."option-value"}}
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			return New-Object NetApp.SDK.NaSnapshotAutoDelete -ArgumentList @(
			$name,
			$result."state",
			$result."commitment",
			$result."trigger",
			$result."target_free_space",
			$result."delete_order",
			$result."defer_delete",
			$result."prefix"
			)
		}
	}
}
function Set-NaSnapshotAutoDelete {
	<#
	.Synopsis
   		Returns the current snapshot autodelete settings.
	.Description
	 	Returns the current snapshot autodelete settings.
	.Parameter Name
		Name of the existing volume for which we want snapshot autodelete settings 
	.Parameter Enable
		Turn on Autodelete for the volume.
	.Parameter Disable
		Turn off Autodelete for the volume.
	.Parameter	Commitment
		This option determines the snapshots which snapshot autodelete is allowed to
		delete to get back space. Setting this option to "try" only permits the
		snapshots which are not locked by data protection utilities (dump, mirroring,
		NDMPcopy) and data backing functionalities (volume and LUN clones) to be
		deleted. Setting this option to "disrupt" only permits the snapshots which are
		not locked by data backing functionalities (volume and LUN clones) to be
		deleted.
	.Parameter Trigger
		This option determines the condition in which snapshots should be automatically
		deleted. Setting this option to "volume" triggers snapshot autodelete to run
		when the volume is near full. Setting this option to "snap_reseve" triggers
		snapshot autodelete to run when the snap reserve of the volume is near full.
		Setting this option to "space_reserve" triggers snapshot autodelete to run when
		the space reserved in the volume is near full.
	.Parameter TargetFreeSpace
		This option determines when snapshot autodelete should stop deleting
        snapshot. Depending on the trigger, snapshots are deleted till we reach the
        target free space percentage.
	.Parameter DeleteOrder
		This option determines if the oldest or newest snapshot is deleted first. 
	.Parameter DeferDelete
        This option determines which kind of snapshots to delete in the end.
        Setting this option value to "scheduled" will delete the snapshots created by
        the snapshot scheduler last. Setting this option value to "user_created" will
        delete the snapshots not created by the snapshot scheduler last. Setting this
        option value to "prefix" will delete the snapshots matching the prefix string
        to be deleted last. Setting this option value to "none" will disable the above
	.Parameter Prefix
	    This option can be set to provide the prefix string for the "prefix" value
        of the "defer_delete" option. The prefix string length can be 15 char long.
	.Parameter Server
   		NaServer to query
	.Example
    	# Enable autodelete policy for vol0
    	PS > Set-NaSnapshotAutoDelete -Name vol0 -Enable
	.Outputs
    	NetApp.SDK.NaSnapshotAutoDelete[]
    .Link
    	Get-NaSnapshotAutoDelete
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 

	[Parameter(position=0,ParameterSetName="enable",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Parameter(position=0,ParameterSetName="disable",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Parameter(position=0,ParameterSetName="commitment",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Parameter(position=0,ParameterSetName="trigger",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Parameter(position=0,ParameterSetName="targetFreeSpace",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Parameter(position=0,ParameterSetName="deleteOrder",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Parameter(position=0,ParameterSetName="deferDelete",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Parameter(position=0,ParameterSetName="prefix",Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
	[Alias("volume")]
	[STRING]
	$Name,

	[Parameter(ParameterSetName="enable")]
	[switch]
	$enable,

	[Parameter(ParameterSetName="disable")]
	[switch]
	$disable,

	[Parameter(ParameterSetName="commitment",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="valid options are try, disrupt")]
	[ValidateSet("try","disrupt")]
	[string]
	$Commitment,

	[Parameter(ParameterSetName="trigger",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="valid values are volume,snap_reserve,space_reserve")]
	[ValidateSet("volume", "snap_reserve", "space_reserve")]
	[string]
	$Trigger,

	[Parameter(ParameterSetName="targetFreeSpace",ValueFromPipelineByPropertyName=$TRUE)]
	[int]
	$TargetFreeSpace,

	[Parameter(ParameterSetName="deleteOrder",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="This option determines if the oldest or newest snapshot is deleted first.")]
	[ValidateSet("newest_first", "oldest_first")]
	[string]
	$DeleteOrder,

	[Parameter(ParameterSetName="deferDelete",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="This option determines which kind of snapshots to delete in the end.")]
	[ValidateSet("scheduled","user_created","prefix","none")]
	[string]
	$DeferDelete,

	[Parameter(ParameterSetName="prefix",ValueFromPipelineByPropertyName=$TRUE,HelpMessage="This option can be set to provide the prefix string for the 'prefix' value of the -deferDelete option.")]
	[ValidateLength(1,15)]
	[string]
	$Prefix,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-autodelete-set-option")
		$request.AddNewChild("volume",$Name)
		switch ($PSCmdlet.ParametersetName)
		{
			"enable" 
			{
				$request.AddNewChild("option-name","state")
				$request.AddNewChild("option-value","on")
				$msg = "Enabling Snapshot Auto-Delete" 
			}
			"disable"
			{
				$request.AddNewChild("option-name","state")
				$request.AddNewChild("option-value","off")
				$msg = "Disabling Snapshot Auto-Delete" 
			}
			"commitment" 
			{
				$request.AddNewChild("option-name","commitment")
				$request.AddNewChild("option-value",$commitment)
				$msg = "Setting Auto-Delete Commitment to $commitment " 
			}
			"trigger" 
			{
				$request.AddNewChild("option-name","trigger")
				$request.AddNewChild("option-value",$trigger)
				$msg = "Setting Auto-Delete trigger to $trigger " 
			}
			"targetFreeSpace"
			{
				$request.AddNewChild("option-name","target_free_space")
				$request.AddNewChild("option-value",$targetFreeSpace)
				$msg = "Setting Auto-Delete Target FreeSpace to $targetFreeSpace " 
			}
			"deleteOrder"
			{
				$request.AddNewChild("option-name","delete_order")
				$request.AddNewChild("option-value",$deleteOrder)
				$msg = "Setting Auto-Delete delete order to $deleteOrder " 
			}
			"deferDelete"
			{
				$request.AddNewChild("option-name","defer_delete")
				$request.AddNewChild("option-value",$deferDelete)
				$msg = "Setting Auto-Delete defer delete to $deferDelete " 
			}
			"prefix" {
				$request.AddNewChild("option-name","prefix")
				$request.AddNewChild("option-value",$prefix)
				$msg = "Setting Auto-Delete defer delete prefix to $prefix " 
			}
		}
		if (($pscmdlet.ShouldProcess($Name, $msg))) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaSnapshotAutoDelete -name $Name -Server $Server
			}
		} 
	}
}
function Get-NaSnapshotSchedule {
	<#
	.Synopsis
   		Obtain the current snapshot schedule on a specified volume.
	.Description
	 	Obtain the current snapshot schedule on a specified volume. Error Returns: Invalid volume name.
	.Parameter Name
		This the volume name where the snapshots are located. 
	.Parameter Server
   		NaServer to query
	.Outputs
    	NetApp.SDK.NaSnapshotSchedule[]
    .Link
    	Set-NaSnapshotSchedule
    .Example
    	Get the current snapshot schedual for vol0
    	PS > Get-NaSnapshotSchedule vol0
	#>
	[CmdletBinding(SupportsShouldProcess=$false,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
		[Alias("volume")]
		[STRING]
		$Name,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-get-schedule")
		$request.AddNewChild("volume",$name)
		try {
			$result  = ([xml]$server.InvokeElem($request)).results
		}
		catch [NetApp.Manage.NaApiFailedException]{
			Write-Warning $_.Exception.GetBaseException().message
			$result = $null
			continue;
		}
		if ($?){
			return New-Object NetApp.SDK.NaSnapshotSchedule -ArgumentList @(
				$Name,
				$result."days",
				$result."hours",
				$result."minutes",
				$result."weeks",
				$result."which-hours",
				$result."which-minutes"
			)
		}
	}
}
function Set-NaSnapshotSchedule {
	<#
	.Synopsis
   		Set the snapshot schedule on a specified volume.
	.Description
        Set the snapshot schedule on a specified volume. If number of snapshots
        requested is greater than ONTAP allows, then ESNAPTOOMANY will be returned with
        the maximum allow snapshots in the reason.
	.Parameter Name
		This the volume name where the snapshots are located. 
	.Parameter Days
		Number of snapshots taken daily to keep on line. If not provided, the number of
        daily snapshots is left at the previous value.
	.Parameter Hours
	    Number of snapshots taken hourly to keep on line. If not provided, the number
        of weekly snapshots is left at the previous value.
	.Parameter Minutes
		Number of snapshots taken minutely to keep on line. If not provided, the number
		of minutely snapshots is left at the previous value.
	.Parameter Weeks
        Number of snapshots taken weekly to keep on line. If not provided, the number
        of weekly snapshots is left at the previous value.
	.Parameter WhichHours
        Comma-separated list of the hours at which the hourly snapshots are created. If
        hours is 0, which-hours is ignored and cleared.
	.Parameter WhichMinutes
        Comma-separated list of the minutes at which the minutely snapshots are
        created. If minutes is 0, which-minutes is ignored and cleared.
	.Parameter Server
   		NaServer to query
	.Outputs
    	NetApp.SDK.NaSnapshotSchedule[]
    .Link
    	Get-NaSnapshotSchedule
    .Example 
    	# Set the snapshot schedual on vol0 to keep 3 weekly 7 daily and 12 hourly snapshots
    	# snapping every two hours.
    	PS > Set-NaSnapshotSchedule -Name vol0 -Weeks 3 -Days 7 -Hours 12 -WhichHours "0,2,4,6,8,12,14,16,18,22"
    .Example
    	# copy the snapshot schedual from vol1 to vol2
    	PS > Get-NaSnapshotSchedule -name vol0 | Set-NaSnapshotSchedule -name vol1
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="The name of the volume for which we want status information.")]
		[Alias("Volume")]
		[STRING]
		$Name,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Number of snapshots taken daily to keep on line.")]
		[int]
		$Days,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Number of snapshots taken hourly to keep on line.")]
		[int]
		$Hours,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Number of snapshots taken minutely to keep on line. ")]
		[int]
		$Minutes,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Number of snapshots taken weekly to keep on line.")]
		[int]
		$Weeks,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Comma-separated list of the hours at which the hourly snapshots are created.")]
		[string]
		$WhichHours,
	
		[Parameter(ValueFromPipelineByPropertyName=$TRUE,HelpMessage="Comma-separated list of the minutes at which the minutely snapshots are created.")]
		[string]
		$WhichMinutes,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	process{
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("snapshot-set-schedule")
		$request.AddNewChild("volume",$Name)
		if ($Days) {
			$request.AddNewChild("days",$Days)
		}
		if ($Hours) {
			$request.AddNewChild("hours",$Hours)
		}
		if ($Minutes) {
			$request.AddNewChild("minutes",$Minutes)
		}
		if ($Weeks) {
			$request.AddNewChild("weeks",$Weeks)
		}
		if ($WhichHours) {
			$request.AddNewChild("which-hours",$WhichHours)
		}
		if ($WhichMinutes) {
			$request.AddNewChild("which-minutes",$WhichMinutes)
		}
		if ($pscmdlet.ShouldProcess($server.server, "Setting ($Name) Auto-Snapshot schedule ")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
			if ($?){
				return Get-NaSnapshotSchedule -Name $Name -Server $server
			}
		} 
	}
}
function Start-NaSnapshotCheckPoint {
	<#
	.Synopsis
   		Starts the checkpoint cycle for externally synchronized checkpoints in the
        filer.
	.Description
        Starts the checkpoint cycle for externally synchronized checkpoints in the
        filer. This operation fences the specified volumes and returns "success" (if
        successful). If the API returns "success", the call starts a snap create
        operation in these volumes. If the API returns "success", this operation SHOULD
        be followed by Stop-NaSnapshotCheckPoint.
	.Parameter Name
        The provided name of the snapshot that is created in each volume. This name is
        the unique identifier by which the calling agent identifies the snapshots that
        constitute a checkpoint. The maximum length is 255 characters. (= MAXNAMLEN)
    .Parameter Volumes
    	Volumes in this filer that is part of this CG operation.
    .Parameter Timeout
    	Timeout selector. Possible vaules are "urgent", "medium" or "relaxed". If no 
    	value is specified, the default value is "medium". 
	.Parameter Server
   		NaServer to query
	.Outputs
    	string
    .Example
    	$cp = Start-NaSnapshotCheckPoint -Name Snapshot1 -Volume "vol0","vol1"
		Stop-NaSnapshotCheckPoint -CheckPoint $CP	
	.Link
    	Stop-NaSnapshotCheckPoint
    	Remove-NaSnapshotCheckPoint
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(position=0,Mandatory=$TRUE,HelpMessage="The provided name of the snapshot that is created in each volume.")]
		[STRING]
		$name,
	
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="volumes in this filer that are part of the CG operation")]
		[string[]]
		$Volume,
	
		[Parameter(Mandatory=$False,HelpMessage="Timeout selector. Possible vaules are 'urgent', 'medium' or 'relaxed'.")]
		[ValidateSet("urgent", "medium", "relaxed")]
		[STRING]
		$timeout,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$vols = new-object netapp.manage.naelement("volumes")
		foreach ($v in $Volume) {
			$vols.AddNewChild("volume-name",$v) 
		}
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("cg-start")
		$request.AddChildElement($vols)
		$request.AddNewChild("snapshot",$name)
		if ($timeout) {
			$request.AddNewChild("timeout",$timeout)
		}
		if ($pscmdlet.ShouldProcess($Server.Server, "Starting synchronized Checkpoint operation $($Name) on $($volume -join ', ')")) {
			try {
				$result  = ([xml]$server.InvokeElem($request)).results
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				$result = $null
				continue;
			}
			if ($?){
				return $result | Select @{e={$_."cg-id"};n='Checkpoint'}
			} 
		}
	}
}
function Stop-NaSnapshotCheckPoint {
	<#
	.Synopsis
   		Commits the snapshots that were started during the preceeding CheckPoint.
	.Description
        Commits the snapshots that were started during the preceeding 
		Stop-NaSnapshotCheckPoint call that returned the cg-id key, and unfences
		the volumes that were fenced
	.Parameter Checkpoint
       	Key to identify the ongoing cg operation. 
    .Parameter Server
   		NaServer to query
    .Example
    	$cp = Start-NaSnapshotCheckPoint -Name Snapshot1 -Volume "vol0","vol1"
		Stop-NaSnapshotCheckPoint -CheckPoint $CP	
	.Link
    	Start-NaSnapshotCheckPoint
    	Remove-NaSnapshotCheckPoint
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
	[Parameter(position=0,ValueFromPipelineByPropertyName=$TRUE,Mandatory=$TRUE,HelpMessage="The Checkpoint ID of the cg operation to be commited.")]
	[STRING]
	$Checkpoint,

	[Parameter(HelpMessage="NaServer to query")]
	[NetApp.SDK.NaServer] 
	$server = (Get-NaServer)
	)
	process {
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("cg-commit")
		$request.AddNewChild("cg-id",$Checkpoint)
		if ($pscmdlet.ShouldProcess($Server.Server, "Commiting snapshots from Checkpoint $($Checkpoint)")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			}
		} 
	}
}
function Remove-NaSnapshotCheckPoint {
	<#
	.Synopsis
   		Deletes the snaps assiciated with a CG checkpoint in this filer.
	.Description
        Deletes the snaps assiciated with a CG checkpoint in this filer.
	.Parameter Name
       	The name of the snapshot that is deleted in each volume.
    .Parameter Volume
    	A list of volumes in this filer that is part of this CG operation.
    .Parameter Server
   		NaServer to query
    .Example
    	$cp = Start-NaSnapshotCheckPoint -Name Snapshot1 -Volume "vol0","vol1"
		Stop-NaSnapshotCheckPoint -CheckPoint $CP	
	.Link
    	Stop-NaSnapshotCheckPoint
    	Start-NaSnapshotCheckPoint
	#>
	[CmdletBinding(SupportsShouldProcess=$True,SupportsTransactions=$False,ConfirmImpact="low",DefaultParameterSetName="")]
	param ( 
		[Parameter(position=0,Mandatory=$TRUE,HelpMessage="The name of the snapshot that is deleted in each volume.")]
		[STRING]
		$name,
	
		[Parameter(Mandatory=$TRUE,ValueFromPipelineByPropertyName=$TRUE,HelpMessage="volumes in this filer that are part of the CG operation")]
		[STRING[]]
		$Volume,
	
		[Parameter(HelpMessage="NaServer to query")]
		[NetApp.SDK.NaServer] 
		$server = (Get-NaServer)
	)
	Process {
		$vols = new-object netapp.manage.naelement("volumes")
		foreach ($v in $Volume) {
			$vols.AddNewChild("volume-name",$v) 
		}
		$request = New-Object Netapp.Manage.NaElement -ArgumentList @("cg-delete")
		$request.AddChildElement($vols)
		$request.AddNewChild("snapshot",$name)
		if ($pscmdlet.ShouldProcess($Server.Server, "Removing synchronized Checkpoint operation $($Name) from $($volume -join ', ')")) {
			try {
				$server.InvokeElem($request)|out-null
			}
			catch [NetApp.Manage.NaApiFailedException]{
				Write-Warning $_.Exception.GetBaseException().message
				continue;
			} 
		}
	}
}
